/**
 * TempMsgPriorityQueueImpl.java<br>
 *
 * @author aaronwong.sd@foxmail.com
 * @version 下午2:13:10
 */
package com.iwechat.service.queue;

import java.text.NumberFormat;
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import org.springframework.stereotype.Component;

import com.iwechat.mybatis.generator.model.TemplateMessage;
import com.iwechat.service.TempMsgPriorityQueue;
import com.iwechat.util.PropertyUtils;

/**
 * 模板消息优先级队列实现
 *
 * @author aaronwong.sd@foxmail.com
 */
@Component("RamPriorityQuenue")
public class TempMsgPriorityQueueImpl implements TempMsgPriorityQueue {
    /** 比较器 */
    private final Comparator<TemplateMessage> OrderIsdn = new Comparator<TemplateMessage>() {
                                                            @Override
                                                            public int compare(TemplateMessage o1, TemplateMessage o2) {
                                                                int ret = 0;
                                                                if (o1 == null || o2 == null || o1 == o2) {
                                                                    ret = 0;
                                                                } else {
                                                                    // 比较优先级
                                                                    if (o1.getPriority() > o2.getPriority()) {
                                                                        ret = 1;
                                                                    } else if (o1.getPriority() < o2.getPriority()) {
                                                                        ret = -1;
                                                                    } else {
                                                                        // 比较创建时间,越早优先级越高
                                                                        if (o1.getCreateTime().getTime() < o2.getCreateTime().getTime()) {
                                                                            ret = 1;
                                                                        } else if (o1.getCreateTime().getTime() > o2.getCreateTime().getTime()) {
                                                                            ret = -1;
                                                                        } else {
                                                                            ret = 0;
                                                                        }
                                                                    }
                                                                }
                                                                return ret;
                                                            }

                                                        };
    private int                               capacity;
    {
        capacity = 1024;
        capacity = PropertyUtils.getInstance().getIntValue("settings", "template.message.queue.capacity");
    }
    private final PriorityBlockingQueue<TemplateMessage> queue  = new PriorityBlockingQueue<TemplateMessage>((int) (1.1 * capacity), OrderIsdn);

    private AtomicLong                                   passed = new AtomicLong(0);

    /*
     * (non-Javadoc)
     *
     * @see com.iwechat.service.TempMsgPriorityQueue#put(com.iwechat.mybatis.generator.model.TemplateMessage)
     */
    @Override
    public boolean offer(TemplateMessage m) {
        if (m != null) {
            return this.queue.offer(m, 5, TimeUnit.SECONDS);
        } else {
            return true;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see com.iwechat.service.TempMsgPriorityQueue#remove()
     */
    @Override
    public TemplateMessage take() {
        try {
            passed.incrementAndGet();
            return this.queue.take();
        } catch (InterruptedException e) {
            return null;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see com.iwechat.service.TempMsgPriorityQueue#monitor()
     */
    @Override
    public String monitor() {
        NumberFormat nt = NumberFormat.getPercentInstance();
        nt.setMinimumFractionDigits(2);
        StringBuffer buffer = new StringBuffer(256);
        buffer.append(this);
        buffer.append("\n");
        buffer.append("### size : " + this.queue.size());
        buffer.append("\n");
        buffer.append("### percent : " + nt.format((this.queue.size() + 0.0D) / this.capacity));
        buffer.append("\n");
        buffer.append("### capacity : " + this.capacity);
        buffer.append("\n");
        buffer.append("### passed : " + this.passed.get());
        return buffer.toString();
    }

    /**
     * 避免扫描的低优先级消息占领缓存队列 获取空闲空间最大不超过capacity的80%。<br>
     * 实际效果是当缓存空间达到80%时不会进行数据库扫描
     *
     * @see com.iwechat.service.TempMsgPriorityQueue#getFreeSize()
     */
    @Override
    public int getFreeSize() {

        int available = (int) (this.capacity * 0.8);
        int free = available - this.queue.size();
        if (free < 0) {
            free = 0;
        }
        return free;
    }

    /**
     * 获取空闲率<br>
     * 空闲率>50才会进行消息扫描
     * 
     * @see com.iwechat.service.TempMsgPriorityQueue#getFreePercent()
     */
    @Override
    public int getFreePercent() {
        int percent = (int) (100 * (this.capacity - this.queue.size()) / (this.capacity + 0.0));
        return percent;
    }

}
